<?php

    #-------------------------------------------------------------#
	# This file is part of the Tekuna MVC Microframework for PHP. #
	# (c) 2009 Niels Jäckel <niels.jaeckel@tekuna.org>            #
	# Please visit http://tekuna.org/ for more information.       #
	#                                                             #
	# This software is licensed under the MIT License. Please     #
	# view the LICENSE file for the full text of this license.    #
    #-------------------------------------------------------------#


	Tekuna :: load('org.tekuna.core.application.DefaultModuleProcessor');
	Tekuna :: load('org.tekuna.core.config.ApplicationConfigurationBuilder');


	class ModuleProcessorTest extends AbstractTekunaTestCase {


		public function testFragments() {

			// build the config
			$objConfig = ApplicationConfigurationBuilder :: buildConfigurationFromXMLFile(APPLICATION_ROOT .'testConfigs/ModuleProcessorTestConfig.xml');

			// get the test module
			$objModule = $objConfig -> getModuleForURL('/testFragment/');

			// build the context
			$objContext = new TekunaApplicationContext();
			$objContext -> setApplicationLanguage('en');
			$objContext -> setApplicationConfiguration($objConfig);

			// get module processor
			$objProcessor = new DefaultModuleProcessor($objContext);
			$arrSlots = $objProcessor -> processModule($objModule);

			// test fragment1 result
			$this -> assertIdentical($arrSlots['fragment1'], 'Foo result');

			// test exception output result
			$this -> assertIdentical(substr_count($arrSlots['fragment2'], 'fragment2'), 1);
			$this -> assertIdentical(substr_count($arrSlots['fragment2'], 'TekunaApplicationException'), 1);
			$this -> assertIdentical(substr_count($arrSlots['fragment2'], 'fragments/en'. DIRECTORY_SEPARATOR .'nonExistentFragment'), 1);
		}


		public function testControllers() {

			// build the config
			$objConfig = ApplicationConfigurationBuilder :: buildConfigurationFromXMLFile(APPLICATION_ROOT .'testConfigs/ModuleProcessorTestConfig.xml');

			// get the test module
			$objModule = $objConfig -> getModuleForURL('/testController/');

			// build the context
			$objContext = new TekunaApplicationContext();
			$objContext -> setApplicationLanguage('en');
			$objContext -> setApplicationConfiguration($objConfig);
			$objContext -> setURLInformation(new URLInformation());

			// get module processor
			$objProcessor = new DefaultModuleProcessor($objContext);
			$arrSlots = $objProcessor -> processModule($objModule);

			// test controller1 result
			$this -> assertIdentical($arrSlots['controller1'], 'testOutput');

			// test exception output result
			$this -> assertIdentical(substr_count($arrSlots['controller2'], 'controller2'), 1);
			$this -> assertIdentical(substr_count($arrSlots['controller2'], 'TekunaApplicationException'), 1);
			$this -> assertIdentical(substr_count($arrSlots['controller2'], 'class file not found'), 1);
		}


		public function testRoutes() {

			// basic routes
			$this -> assertIdentical($this -> getRouteTestOutput(''), '');
			$this -> assertIdentical($this -> getRouteTestOutput('foo.html'), 'Foo result');
			$this -> assertIdentical($this -> getRouteTestOutput('bar.do'), 'Bar result');

			// directories
			$this -> assertIdentical($this -> getRouteTestOutput('directoryListing/'), 'Foo result');
			$this -> assertIdentical($this -> getRouteTestOutput('directoryListing/foo.html'), '');
			$this -> assertIdentical($this -> getRouteTestOutput('directoryListing/foo/bar.html'), '');

			// file wildcard
			$this -> assertIdentical($this -> getRouteTestOutput('fileWildcard/foo.html'), 'Foo result');
			$this -> assertIdentical($this -> getRouteTestOutput('fileWildcard/bar.html'), 'Foo result');
			$this -> assertIdentical($this -> getRouteTestOutput('fileWildcard/baz.html'), 'Foo result');
			$this -> assertIdentical($this -> getRouteTestOutput('fileWildcard/.html'), 'Foo result');
			$this -> assertIdentical($this -> getRouteTestOutput('fileWildcard/subdirectory/foo.html'), '');

			// subdirectories wildcard
			$this -> assertIdentical($this -> getRouteTestOutput('directoryWildcard/foo.html'), 'Bar result');
			$this -> assertIdentical($this -> getRouteTestOutput('directoryWildcard/bar.html'), 'Bar result');
			$this -> assertIdentical($this -> getRouteTestOutput('directoryWildcard/baz.html'), 'Bar result');
			$this -> assertIdentical($this -> getRouteTestOutput('directoryWildcard/.html'), 'Bar result');
			$this -> assertIdentical($this -> getRouteTestOutput('directoryWildcard/subdirectory/foo.html'), 'Bar result');
			$this -> assertIdentical($this -> getRouteTestOutput('directoryWildcard/subdirectory/subsubdirectory/foo.html'), 'Bar result');

			// directory catch all
			$this -> assertIdentical($this -> getRouteTestOutput('directoryAll/'), 'Foo result');
			$this -> assertIdentical($this -> getRouteTestOutput('directoryAll/foo.html'), 'Foo result');
			$this -> assertIdentical($this -> getRouteTestOutput('directoryAll/foo/bar.html'), '');

			// subdirectories catch all
			$this -> assertIdentical($this -> getRouteTestOutput('catchAll/'), 'Bar result');
			$this -> assertIdentical($this -> getRouteTestOutput('catchAll/foo'), 'Bar result');
			$this -> assertIdentical($this -> getRouteTestOutput('catchAll/foo/bar/baz.html'), 'Bar result');

			// multiple matches
			$this -> assertIdentical($this -> getRouteTestOutput('multipleMatches/foo/bar/baz.html'), 'Foo result');
			$this -> assertIdentical($this -> getRouteTestOutput('multipleMatches/foo/bar/baz/foofoo.html'), '');

			$this -> assertIdentical($this -> getRouteTestOutput('multipleMatches2/foo/bar/baz.html'), 'Bar result');
			$this -> assertIdentical($this -> getRouteTestOutput('multipleMatches2/foo/bar/foo/bar/foo/bar/foo/bar/baz.html'), 'Bar result');
			$this -> assertIdentical($this -> getRouteTestOutput('multipleMatches2/x/baz.html'), 'Bar result');

			// test matches URL parts
			$this -> assertIdentical($this -> getMatchesOutput('multipleMatches/a/b/c'), array(1 => 'a', 2 => 'b', 3 => 'c'));
			$this -> assertIdentical($this -> getMatchesOutput('multipleMatches/a/b/c/d'), array());
			$this -> assertIdentical($this -> getMatchesOutput('multipleMatches2/a/b/c.html'), array(1 => 'a/b', 2 => 'c'));
			$this -> assertIdentical($this -> getMatchesOutput('multipleMatches2/a/b/c/d/e/f.html'), array(1 => 'a/b/c/d/e', 2 => 'f'));

			// test controllers in routes
			$this -> assertIdentical($this -> getRouteTestOutput('controllerTest/foo.html'), 'testOutput');
			$this -> assertIdentical($this -> getRouteTestOutput('controllerTest/bar.html'), 'testOutput');
			$this -> assertIdentical($this -> getRouteTestOutput('controllerTest/foo/bar.do'), 'testOutput');
			$this -> assertIdentical($this -> getRouteTestOutput('controllerTest/foo/bar/baz/test.do'), 'testOutput');
		}


		protected function getRouteTestOutput($sRequestURL) {

			// build the config
			$objConfig = ApplicationConfigurationBuilder :: buildConfigurationFromXMLFile(APPLICATION_ROOT .'testConfigs/ModuleProcessorTestConfig.xml');

			// build the URL information object
			$objURLInfo = new URLInformation();
			$objURLInfo -> setComponentURL($sRequestURL);

			// get the test module
			$objModule = $objConfig -> getModuleForURL('/testRoutes/');

			// build the context
			$objContext = new TekunaApplicationContext();
			$objContext -> setApplicationLanguage('en');
			$objContext -> setApplicationConfiguration($objConfig);
			$objContext -> setURLInformation($objURLInfo);

			// get module processor
			$objProcessor = new DefaultModuleProcessor($objContext);
			$arrSlots = $objProcessor -> processModule($objModule);

			return $arrSlots['output'];
		}


		protected function getMatchesOutput($sRequestURL) {

			// build the config
			$objConfig = ApplicationConfigurationBuilder :: buildConfigurationFromXMLFile(APPLICATION_ROOT .'testConfigs/ModuleProcessorTestConfig.xml');

			// build the URL information object
			$objURLInfo = new URLInformation();
			$objURLInfo -> setComponentURL($sRequestURL);

			// get the test module
			$objModule = $objConfig -> getModuleForURL('/testRoutes/');

			// build the context
			$objContext = new TekunaApplicationContext();
			$objContext -> setApplicationLanguage('en');
			$objContext -> setApplicationConfiguration($objConfig);
			$objContext -> setURLInformation($objURLInfo);

			// get module processor
			$objProcessor = new DefaultModuleProcessor($objContext);
			$arrSlots = $objProcessor -> processModule($objModule);

			return $objURLInfo -> getMatchedURLParts();
		}


		public function testStatuses() {

			// build the config
			$objConfig = ApplicationConfigurationBuilder :: buildConfigurationFromXMLFile(APPLICATION_ROOT .'testConfigs/ModuleProcessorTestConfig.xml');

			// build the response object
			$objResponse = new Response();

			// build the URL information object
			$objURLInfo = new URLInformation();

			// build the context
			$objContext = new TekunaApplicationContext();
			$objContext -> setResponse($objResponse);
			$objContext -> setApplicationLanguage('en');
			$objContext -> setApplicationConfiguration($objConfig);
			$objContext -> setURLInformation($objURLInfo);

			// get module processor
			$objProcessor = new DefaultModuleProcessor($objContext);

			// process the test modules
			$objModule = $objConfig -> getModuleForURL('/testStatus201/');
			$arrSlots = $objProcessor -> processModule($objModule);
			$this -> assertIdentical($objResponse -> getStatus(), 201);

			$objModule = $objConfig -> getModuleForURL('/testStatus202/');
			$arrSlots = $objProcessor -> processModule($objModule);
			$this -> assertIdentical($objResponse -> getStatus(), 202);

			$objModule = $objConfig -> getModuleForURL('/testStatus203/');
			$arrSlots = $objProcessor -> processModule($objModule);
			$this -> assertIdentical($objResponse -> getStatus(), 203);

			$objModule = $objConfig -> getModuleForURL('/testStatus204/');
			$arrSlots = $objProcessor -> processModule($objModule);
			$this -> assertIdentical($objResponse -> getStatus(), 204);
		}
	}



